`timescale 1ns / 1ps
/******************************************************************************
*                                                                             *
* UTICA softcore v0.1                                                         *
*                                                                             *
* Copyright (c) 2012 Andrew D. Zonenberg                                      *
* All rights reserved.                                                        *
*                                                                             *
* Redistribution and use in source and binary forms, with or without modifi-  *
* cation, are permitted provided that the following conditions are met:       *
*                                                                             *
*    * Redistributions of source code must retain the above copyright notice  *
*      this list of conditions and the following disclaimer.                  *
*                                                                             *
*    * Redistributions in binary form must reproduce the above copyright      *
*      notice, this list of conditions and the following disclaimer in the    *
*      documentation and/or other materials provided with the distribution.   *
*                                                                             *
*    * Neither the name of the author nor the names of any contributors may be*
*      used to endorse or promote products derived from this software without *
*      specific prior written permission.                                     *
*                                                                             *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF        *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN     *
* NO EVENT SHALL THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT,         *
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT    *
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   *
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY       *
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT         *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF    *
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.           *
*                                                                             *
******************************************************************************/

/**
	@brief A parameterizable width 32-level LUT RAM
	
	TODO: parameterizable depth?
 */
module LutramMacroDP(clk, porta_we, porta_addr, porta_din, porta_dout, portb_addr, portb_dout);

	////////////////////////////////////////////////////////////////////////////////////////////////
	// I/O and parameter declarations

	parameter WIDTH = 16;
	
	input wire clk;
	input wire porta_we;
	input wire[4:0] porta_addr;
	input wire[WIDTH-1:0] porta_din;
	output wire[WIDTH-1:0] porta_dout;
	input wire[4:0] portb_addr;
	output wire[WIDTH-1:0] portb_dout;
	
	////////////////////////////////////////////////////////////////////////////////////////////////
	// The RAM itself
	
	genvar i;
	generate
		for(i=0; i<WIDTH; i = i+1) begin: ramblock
			LutramPrimitiveWrapper rambit (
				.clk(clk), 
				.porta_we(porta_we), 
				.porta_addr(porta_addr), 
				.porta_din(porta_din[i]), 
				.porta_dout(porta_dout[i]), 
				.portb_addr(portb_addr), 
				.portb_dout(portb_dout[i])
				);
		end
	endgenerate

endmodule

/**
	@brief Dumb wrapper around a single LUTRAM to use vector addresses
 */
module LutramPrimitiveWrapper(clk, porta_we, porta_addr, porta_din, porta_dout, portb_addr, portb_dout);
	
	input wire clk;
	input wire porta_we;
	input wire[4:0] porta_addr;
	input wire porta_din;
	output wire porta_dout;
	
	input wire[4:0] portb_addr;
	output wire portb_dout;
	 
	RAM32X1D #(.INIT(32'h00000000)) ram (
		.WCLK(clk),
		.WE(porta_we),
		.D(porta_din),
		.SPO(porta_dout),
		.A0(porta_addr[0]),
		.A1(porta_addr[1]),
		.A2(porta_addr[2]),
		.A3(porta_addr[3]),
		.A4(porta_addr[4]),
		
		.DPO(portb_dout),
		.DPRA0(portb_addr[0]),
		.DPRA1(portb_addr[1]),
		.DPRA2(portb_addr[2]),
		.DPRA3(portb_addr[3]),
		.DPRA4(portb_addr[4])
	);
endmodule
